<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <div id="waveform"></div>


  <button onclick="show()">测试测试</button>

</body>
<script type="module">
  import WaveSurfer from 'https://unpkg.com/wavesurfer.js@7/dist/wavesurfer.esm.js'
  import RegionsPlugin from 'https://unpkg.com/wavesurfer.js@7/dist/plugins/regions.esm.js'
  import TimelinePlugin from 'https://unpkg.com/wavesurfer.js@7/dist/plugins/timeline.esm.js'
  import Minimap from 'https://unpkg.com/wavesurfer.js@7/dist/plugins/minimap.esm.js'
  import Spectrogram from 'https://unpkg.com/wavesurfer.js@7/dist/plugins/spectrogram.esm.js'
  import {dataArray} from './data.js'


  const audioData = {
    //录音文件长度
    size: 0
    //录音缓存
    , buffer: []
    //输入采样率
    , inputSampleRate: 20000
    //输入采样数位 8, 16
    , inputSampleBits: 16
    //输出采样率
    , outputSampleRate: 20000
    //输出采样数位 8, 16
    , oututSampleBits: 16
    //清空缓存
    , clear: function () {
      this.buffer = [];
      this.size = 0;
    }
    //存放数据到缓存
    , input: function (data) {
      this.buffer.push(new Float32Array(data));
      this.size += data.length;
    }
    //合并压缩
    , compress: function () {
      //合并
      var data = new Float32Array(this.size);
      var offset = 0;
      for (var i = 0; i < this.buffer.length; i++) {
        data.set(this.buffer[i], offset);
        offset += this.buffer[i].length;
      }
      //压缩
      var compression = parseInt(this.inputSampleRate / this.outputSampleRate);
      var length = data.length / compression;
      var result = new Float32Array(length);
      var index = 0, j = 0;
      while (index < length) {
        result[index] = data[j];
        j += compression;
        index++;
      }
      return result;
    }
    //原始数据编码未WAV
    , encodeWAV: function () {
      var sampleRate = Math.min(this.inputSampleRate, this.outputSampleRate);
      var sampleBits = Math.min(this.inputSampleBits, this.oututSampleBits);
      var bytes = this.compress();
      var dataLength = bytes.length * (sampleBits / 8);
      var buffer = new ArrayBuffer(44 + dataLength);
      var data = new DataView(buffer);

      var channelCount = 1;//单声道
      var offset = 0;

      var writeString = function (str) {
        for (var i = 0; i < str.length; i++) {
          data.setUint8(offset + i, str.charCodeAt(i));
        }
      };

      // 资源交换文件标识符
      writeString('RIFF'); offset += 4;
      // 下个地址开始到文件尾总字节数,即文件大小-8
      data.setUint32(offset, 36 + dataLength, true); offset += 4;
      // WAV文件标志
      writeString('WAVE'); offset += 4;
      // 波形格式标志
      writeString('fmt '); offset += 4;
      // 过滤字节,一般为 0x10 = 16
      data.setUint32(offset, 16, true); offset += 4;
      // 格式类别 (PCM形式采样数据)
      data.setUint16(offset, 1, true); offset += 2;
      // 通道数
      data.setUint16(offset, channelCount, true); offset += 2;
      // 采样率,每秒样本数,表示每个通道的播放速度
      data.setUint32(offset, sampleRate, true); offset += 4;
      // 波形数据传输率 (每秒平均字节数) 单声道×每秒数据位数×每样本数据位/8
      data.setUint32(offset, channelCount * sampleRate * (sampleBits / 8), true); offset += 4;
      // 快数据调整数 采样一次占用字节数 单声道×每样本的数据位数/8
      data.setUint16(offset, channelCount * (sampleBits / 8), true); offset += 2;
      // 每样本数据位数
      data.setUint16(offset, sampleBits, true); offset += 2;
      // 数据标识符
      writeString('data'); offset += 4;
      // 采样数据总数,即数据总大小-44
      data.setUint32(offset, dataLength, true); offset += 4;
      // 写入采样数据
      if (sampleBits === 8) {
        for (var i = 0; i < bytes.length; i++, offset++) {
          var s = Math.max(-1, Math.min(1, bytes[i]));
          var val = s < 0 ? s * 0x8000 : s * 0x7FFF;
          val = parseInt(255 / (65535 / (val + 32768)));
          data.setInt8(offset, val, true);
        }
      } else {
        for (var i = 0; i < bytes.length; i++, offset += 2) {
          var s = Math.max(-1, Math.min(1, bytes[i]));
          data.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
        }
      }

      return new Blob([data], { type: 'audio/wav' });
    }
  };

  function loadData() {
    let  channelData = []
    for (let i = 0; i < dataArray.length; i++) {
      // 将2位音频数据映射到-1到1之间
      channelData[i] = (dataArray[i] / 2080) - 1;
    }
    return channelData
  }

  function show() {
    audioData.input(loadData());
    let blob = audioData.encodeWAV()
    console.log(blob);
    const recordedUrl = URL.createObjectURL(blob);


    const options = {
      "container": "#waveform",
      "height": 128,
      "splitChannels": false,
      "normalize": false,
      "waveColor": "#ff4e00",
      "progressColor": "#dd5e98",
      "cursorColor": "#ddd5e9",
      "cursorWidth": 2,
      "barWidth": null,
      "barGap": null,
      "barRadius": null,
      "barHeight": null,
      "barAlign": "",
      "minPxPerSec": 1,
      "fillParent": true,
      url: recordedUrl,
      "mediaControls": true,
      "autoplay": false,
      "interact": true,
      "dragToSeek": false,
      "hideScrollbar": false,
      "audioRate": 1,
      "autoScroll": true,
      "autoCenter": true,
      "sampleRate": 20000,
      plugins: [
        // Register the plugin
        Minimap.create({
          height: 20,
          waveColor: '#ddd',
          progressColor: '#999',
          // the Minimap takes all the same options as the WaveSurfer itself
        }),
      ],
    }

    const wavesurfer = WaveSurfer.create(options)
    wavesurfer.registerPlugin(TimelinePlugin.create())
    wavesurfer.registerPlugin(
      Spectrogram.create({
        labels: true,
        height: 200,
        splitChannels: true,
      }),
    )

  }
  show();
</script>

</html>